package alp.starcode.edms.framework.base;

import alp.starcode.edms.framework.constant.Constant;
import alp.starcode.common.base.exception.DataNotExistException;
import alp.starcode.common.base.exception.OperateException;
import alp.starcode.common.mybatis.util.ColumnUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;
import com.google.common.base.CaseFormat;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 项目基础工具类
 *
 * @author liwang
 * @date 2023/4/11 15:02
 */
public class Base {

    /**
     * 获取最大排序值
     */
    public <T> double getMaxValue(IService<T> databaseDao, SFunction<T, ?> keyField) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(keyField).last("limit 1").orderByDesc(keyField);
        Map<String, Object> objectMap = databaseDao.getMap(lambdaQueryWrapper);
        if (objectMap == null) {
            return 0;
        }
        double maxValue = 0D;
        //遍历获取map中的KEY，并返回对应的Value
        for (Map.Entry<String, Object> entries : objectMap.entrySet()) {
            maxValue = Double.parseDouble(String.valueOf(objectMap.get(entries.getKey())));
            if (0 != maxValue) {
                break;
            }
        }
        return maxValue;
    }

    /**
     * 验证数据是否存在
     */
    public <T> boolean isExists(IService<T> databaseDao, SFunction<T, ?> keyField, Object fieldValue) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(keyField);
        lambdaQueryWrapper.eq(keyField, fieldValue);
        List<T> list = databaseDao.list(lambdaQueryWrapper);
        return CollUtil.isNotEmpty(list);
    }


    /**
     * 验证数据是否存在(不包含逻辑删除数据)
     */
    public <T> boolean isExists(IService<T> databaseDao, SFunction<T, ?> keyField, Object fieldValue, SFunction<T, ?> isDeletedKeyField) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(keyField);
        lambdaQueryWrapper.eq(keyField, fieldValue);
        lambdaQueryWrapper.eq(isDeletedKeyField, 0);
        List<T> list = databaseDao.list(lambdaQueryWrapper);
        return CollUtil.isNotEmpty(list);

    }

    /**
     * 获取相邻节点排序的平均值
     *
     * @param databaseDao   数据操作对象
     * @param keyField      主键字段名称
     * @param keyValue      主键字段值
     * @param orderField    排序字段名称
     * @param moveDirection 移动方向
     */
    public <T> Double getMiddleValue(IService<T> databaseDao, SFunction<T, ?> keyField, String keyValue, SFunction<T, ?> orderField, String moveDirection) {
        //获取角色的排序值
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(orderField);
        queryWrapper.eq(keyField, keyValue);
        T obj = databaseDao.getOne(queryWrapper);
        if (obj == null) {
            throw new DataNotExistException("数据[%s]不存在", keyValue);
        }
        Field declaredField = null;
        //获取模版中的排序字段
        try {
            declaredField = obj.getClass().getDeclaredField(ColumnUtil.getFieldName(orderField));
            // 设置可访问私有属性，默认是不可访问的
            declaredField.setAccessible(true); //NOSONAR 设置私有属性允许访问
        } catch (NoSuchFieldException e) {
            throw new OperateException("获取对象属性异常：" + e.getMessage());
        }
        Double roleOrder;
        try {
            roleOrder = (Double) declaredField.get(obj);
        } catch (IllegalAccessException e) {
            throw new OperateException("获取属性数据异常:" + e.getMessage());
        }
        //查询相邻节点的排序值，并计算出中间排序值
        LambdaQueryWrapper<T> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(orderField).last("limit 1").orderByAsc(orderField);
        double middleOrderValue;
        //排序方式转大写判断
        moveDirection = moveDirection.toUpperCase();
        if (Constant.MOVE_UP.equals(moveDirection)) {
            middleOrderValue = roleOrder / 2;
            lambdaQueryWrapper.lt(orderField, roleOrder);
        } else if (Constant.MOVE_DOWN.equals(moveDirection)) {
            lambdaQueryWrapper.gt(orderField, roleOrder);
            middleOrderValue = roleOrder + 1;
        } else {
            throw new OperateException("[" + moveDirection + "]不支持的排序方式");
        }
        T adjacentNodeMap = databaseDao.getOne(lambdaQueryWrapper);
        if (adjacentNodeMap != null) {
            Double nodeRoleOrder;
            try {
                nodeRoleOrder = (Double) declaredField.get(adjacentNodeMap);
            } catch (IllegalAccessException e) {
                throw new OperateException("获取属性数据异常:" + e.getMessage());
            }
            middleOrderValue = (roleOrder + nodeRoleOrder) / 2;
        }
        return middleOrderValue;
    }

    /**
     * 小数点大于3位时重置显示顺序
     *
     * @param databaseDao 数据操作对象
     * @param orderValue  排序值
     * @param keyField    主键字段
     * @param orderField  排序字段
     */
    public <T> void resetOrder(IService<T> databaseDao, double orderValue, SFunction<T, ?> keyField, SFunction<T, ?> orderField) {
        String middleValueStr = String.valueOf(orderValue);
        int indexOf = middleValueStr.indexOf(".");
        if (indexOf > -1) {
            //获取小数点位数
            int digit = middleValueStr.length() - indexOf - 1;
            if (digit > 3) {
                resetOrder(databaseDao, keyField, orderField);
            }
        }
    }

    /**
     * 重排显示顺序
     *
     * @param databaseDao 数据操作对象
     * @param keyField    主键字段
     * @param orderField  排序字段
     */
    public <T> void resetOrder(IService<T> databaseDao, SFunction<T, ?> keyField, SFunction<T, ?> orderField) {
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(keyField, orderField);
        queryWrapper.orderByAsc(orderField);
        List<T> list = databaseDao.list(queryWrapper);
        Iterator<T> iterator = list.iterator();
        double idx = 1;
        while (iterator.hasNext()) {
            T obj = iterator.next();
            try {
                String entityFieldName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, ColumnUtil.getFieldName(orderField));
                Field declaredField = obj.getClass().getDeclaredField(entityFieldName);
                declaredField.setAccessible(true); //NOSONAR 设置私有属性允许访问
                declaredField.set(obj, idx);  //NOSONAR 设置属性值
                idx++;
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new OperateException("重排显示顺序异常：" + e.getMessage());
            }
        }
        databaseDao.updateBatchById(list);
    }

}
